home *** CD-ROM | disk | FTP | other *** search
/ Turnbull China Bikeride / Turnbull China Bikeride - Disc 2.iso / STUTTGART / LANG / ICON / ICONV8 / Source / Common / C / Popen < prev    next >
Text File  |  1990-09-18  |  7KB  |  409 lines

  1. /* C.Popen: Simulation of pipes */
  2.  
  3. #include <ctype.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include "kernel.h"
  8.  
  9. extern char *mktemp (const char *);
  10.  
  11. static char *strdup (const char *);
  12. static int os_cmd (char *);
  13. static int cmp_cmd (char *, char *);
  14.  
  15. #define MAX_PIPE 20
  16.  
  17. typedef enum
  18. {
  19.     unopened = 0,
  20.     reading,
  21.     writing
  22. }
  23. pipemode;
  24.  
  25. static struct pipe
  26. {
  27.     char *command;    /* The command being executed        */
  28.     char *name;    /* The name of the pipe file        */
  29.     FILE *fd;    /* The file used as a pipe        */
  30.     pipemode pmode;    /* The open mode of the pipe        */
  31.     int retval;    /* The return value of the command    */
  32. }
  33. pipes[MAX_PIPE];
  34.  
  35. FILE *popen (char *command, char *mode)
  36. {
  37.     FILE *current;
  38.     char *name;
  39.     int i;
  40.     pipemode curmode;
  41.     int rval = -1;
  42.     char tmp[11];
  43.  
  44.     /* decide on mode */
  45.     if ( mode[1] != 0 )
  46.         return NULL;
  47.     else if ( *mode == 'r' )
  48.         curmode = reading;
  49.     else if ( *mode == 'w' )
  50.         curmode = writing;
  51.     else
  52.         return NULL;
  53.  
  54.     /* Get a slot in the pipes structure */
  55.     for ( i = 0; i < MAX_PIPE; ++i )
  56.     {
  57.         if ( pipes[i].pmode == unopened )
  58.             break;
  59.     }
  60.  
  61.     if ( i >= MAX_PIPE )
  62.         return NULL;
  63.  
  64.     /* Get a file name to use */
  65.     sprintf(tmp, "Pipe%.2d", i);
  66.     name = mktemp(tmp);
  67.  
  68.     if ( name == NULL )
  69.         return NULL;
  70.  
  71.     /*
  72.      * If we're reading, just call system() to get a file filled
  73.      * with output.
  74.      */
  75.  
  76.     if ( curmode == reading )
  77.     {
  78.         char *tmpname;
  79.         int oscmd = os_cmd(command);
  80.         char cmd[256];
  81.         int n;
  82.  
  83.         if (*command == '%')
  84.         {
  85.             oscmd = 1;
  86.             ++command;
  87.         }
  88.  
  89.         if (!oscmd)
  90.         {
  91.             char *s;
  92.  
  93.             while (*command && isspace(*command))
  94.                 ++command;
  95.  
  96.             s = command;
  97.  
  98.             while (*s && !isspace(*s))
  99.                 ++s;
  100.             
  101.             n = sprintf(cmd, "%.*s > %s%s",
  102.                 s - command, command, name, s);
  103.         }
  104.         else
  105.         {
  106.             tmpname = mktemp("PipeTmp");
  107.  
  108.             if (tmpname == NULL)
  109.             {
  110.                 free(name);
  111.                 return NULL;
  112.             }
  113.  
  114.             n = sprintf(cmd, "%s{ > %s }", command, tmpname);
  115.         }
  116.  
  117.         /* Emergency! Overflow in command buffer! */
  118.         if (n > 255)
  119.         {
  120.             if (oscmd)
  121.             {
  122.                 remove(tmpname);
  123.                 free(tmpname);
  124.             }
  125.             free(name);
  126.             return NULL;
  127.         }
  128.  
  129.         _kernel_setenv("Sys$ReturnCode", "0");
  130.         rval = system(cmd);
  131.  
  132.         if (rval == _kernel_ERROR)
  133.         {
  134.             remove(tmpname);
  135.             free(tmpname);
  136.             free(name);
  137.             return NULL;
  138.         }
  139.  
  140.         if (oscmd)
  141.         {
  142.             int ch;
  143.             FILE *in = fopen(tmpname, "r");
  144.             FILE *out = fopen(name, "w");
  145.  
  146.             if (in == NULL || out == NULL)
  147.             {
  148.                 remove(tmpname);
  149.                 free(tmpname);
  150.                 free(name);
  151.                 return NULL;
  152.             }
  153.  
  154.             /* Strip out CRs from the output */
  155.             while ((ch = getc(in)) != EOF && !ferror(out))
  156.             {
  157.                 if (ch != '\r')
  158.                     putc(ch, out);
  159.             }
  160.  
  161.             /* Did we succeed? */
  162.             ch = (ferror(in) || ferror(out));
  163.  
  164.             /* Tidy up */
  165.             fclose(in);
  166.             fclose(out);
  167.             remove(tmpname);
  168.             free(tmpname);
  169.  
  170.             if (ch)
  171.             {
  172.                 free(name);
  173.                 return NULL;
  174.             }
  175.         }
  176.  
  177.         if ( (current = fopen(name,"r")) == NULL )
  178.         {
  179.             free(name);
  180.             return NULL;
  181.         }
  182.     }
  183.     else
  184.     {
  185.         if ( (current = fopen(name,"w")) == NULL )
  186.         {
  187.             free(name);
  188.             return NULL;
  189.         }
  190.     }
  191.  
  192.     pipes[i].command = strdup(command);
  193.     pipes[i].name = name;
  194.     pipes[i].fd = current;
  195.     pipes[i].pmode = curmode;
  196.     pipes[i].retval = rval;
  197.     return current;
  198. }
  199.  
  200. int pclose (FILE *current)
  201. {
  202.     int rval;
  203.     int i;
  204.  
  205.     /* Get the appropriate slot in thbe pipes structure */
  206.     for ( i = 0; i < MAX_PIPE; ++i )
  207.     {
  208.         if ( pipes[i].fd == current )
  209.             break;
  210.     }
  211.  
  212.     if ( i >= MAX_PIPE )
  213.         return -1;
  214.  
  215.     if ( pipes[i].pmode == reading )
  216.     {
  217.         /* Input pipes are just files we're done with */
  218.         rval = pipes[i].retval;
  219.         fclose(current);
  220.         remove(pipes[i].name);
  221.     }
  222.     else
  223.     {
  224.         /*
  225.          * Output pipes are temporary files we have
  226.          * to cram down the throats of programs.
  227.          */
  228.         char *command = pipes[i].command;
  229.         int oscmd = os_cmd(command);
  230.         int n;
  231.         char cmd[256];
  232.  
  233.         if (*command == '%')
  234.         {
  235.             oscmd = 1;
  236.             ++command;
  237.         }
  238.  
  239.         /* Close the pipe file */
  240.         fclose(current);
  241.  
  242.         /* Create the required command string */
  243.         if (oscmd)
  244.             n = sprintf(cmd, "%s{ < %s }", command, pipes[i].name);
  245.         else
  246.         {
  247.             char *s;
  248.  
  249.             while (*command && isspace(*command))
  250.                 ++command;
  251.  
  252.             s = command;
  253.  
  254.             while (*s && !isspace(*s))
  255.                 ++s;
  256.             
  257.             n = sprintf(cmd, "%.*s < %s%s",
  258.                 s - command, command, pipes[i].name, s);
  259.         }
  260.  
  261.         /* Check for overflow in command buffer */
  262.         if (n > 255)
  263.             rval = -1;
  264.         else
  265.         {
  266.             _kernel_setenv("Sys$ReturnCode", "0");
  267.             rval = system(cmd);
  268.         }
  269.  
  270.         remove(pipes[i].name);
  271.     }
  272.  
  273.     /* clean up current pipe */
  274.     pipes[i].pmode = unopened;
  275.     free(pipes[i].name);
  276.     free(pipes[i].command);
  277.     return rval;
  278. }
  279.  
  280. /* save a string on the heap; return pointer to it */
  281.  
  282. static char *strdup (const char *str)
  283. {
  284.     char *p = malloc(strlen(str)+1);
  285.  
  286.     if (p == NULL)
  287.     {
  288.         fprintf(stderr,"Not enough memory to save string\n");
  289.         exit(1);
  290.     }
  291.  
  292.     return (strcpy(p,str));
  293. }
  294.  
  295. /* Check whether a command is an OS command (binary search on the table
  296.  * os_commands of valid OS commands).
  297.  */
  298.  
  299. static char *os_commands[] =
  300. {
  301.     "access",    "adfs",        "alphabet",    "alphabets",
  302.     "append",    "audio",    "basic",    "breakclr",
  303.     "breaklist",    "breakset",    "build",    "cat",
  304.     "cdir",        "channelvoice",    "close",    "configure",
  305.     "continue",    "copy",        "count",    "countries",
  306.     "country",    "create",    "debug",    "delete",
  307.     "deskfs",    "dir",        "dump",        "echo",
  308.     "enumdir",    "error",    "eval",        "ex",
  309.     "exec",        "fileinfo",    "fontcat",    "fontlist",
  310.     "fx",        "go",        "gos",        "help",
  311.     "iconsprites",    "if",        "ignore",    "info",
  312.     "initstore",    "key",        "keyboard",    "lcat",
  313.     "lex",        "lib",        "list",        "load",
  314.     "memory",    "memorya",    "memoryi",    "modules",
  315.     "obey",        "opt",        "poduleload",    "podules",
  316.     "podulesave",    "pointer",    "print",    "qsound",
  317.     "quit",        "ram",        "remove",    "rename",
  318.     "rmclear",    "rmensure",    "rmfaster",    "rmkill",
  319.     "rmload",    "rmreinit",    "rmrun",    "rmtidy",
  320.     "rommodules",    "run",        "save",        "schoose",
  321.     "scopy",    "screenload",    "screensave",    "sdelete",
  322.     "set",        "seteval",    "setmacro",    "settype",
  323.     "sflipx",    "sflipy",    "sget",        "shadow",
  324.     "shellcli",    "show",        "showregs",    "shut",
  325.     "shutdown",    "sinfo",    "slist",    "sload",
  326.     "smerge",    "snew",        "sound",    "speaker",
  327.     "spool",    "spoolon",    "srename",    "ssave",
  328.     "stamp",    "status",    "stereo",    "tempo",
  329.     "time",        "tuning",    "tv",        "type",
  330.     "unplug",    "unset",    "up",        "voices",
  331.     "volume",    "wimppalette",    "wimpslot",    "wimptask",
  332.     "wipe"
  333. };
  334.  
  335. #define NUM_CMDS (sizeof(os_commands) / sizeof(char *))
  336.  
  337. static int os_cmd (char *cmd)
  338. {
  339.     int low = 0;
  340.     int high = NUM_CMDS - 1;
  341.  
  342.     while (low <= high)
  343.     {
  344.         int mid = (high + low) / 2;
  345.         int i = cmp_cmd(cmd,os_commands[mid]);
  346.  
  347.         if (i == 0)
  348.             return 1;
  349.         else if (i < 0)
  350.             high = mid - 1;
  351.         else
  352.             low = mid + 1;
  353.     }
  354.  
  355.     return 0;
  356. }
  357.  
  358. static int cmp_cmd (char *cmd, char *name)
  359. {
  360.     while (*name && tolower(*cmd) == *name)
  361.         ++name, ++cmd;
  362.  
  363.     if (*name)
  364.         return (tolower(*cmd) - *name);
  365.  
  366.     return (*cmd != '\0' && !isspace(*cmd));
  367. }
  368.  
  369. #ifdef test
  370. int main (int argc, char *argv[])
  371. {
  372.     FILE *fp;
  373.     char *cmd;
  374.  
  375.     if (argc <= 1)
  376.     {
  377.         printf("Usage Popen [cmd or Popen ]cmd\n");
  378.         return 0;
  379.     }
  380.  
  381.     cmd = argv[1];
  382.  
  383.     if (*cmd++ == ']')
  384.     {
  385.         fp = popen(cmd,"w");
  386.         fprintf(fp,"hello\nworld\nhow\nare\nyou\n");
  387.         pclose(fp);
  388.     }
  389.     else
  390.     {
  391.         char buf[500];
  392.         fp = popen(cmd,"r");
  393.         while (!feof(fp))
  394.         {
  395.             if (!fgets(buf,499,fp))
  396.             {
  397.                 printf("Read error!\n");
  398.                 return 1;
  399.             }
  400.             buf[strlen(buf)-1] = 0;
  401.             printf(">%s<\n", buf);
  402.         }
  403.         pclose(fp);
  404.     }
  405.  
  406.     return 0;
  407. }
  408. #endif
  409.